﻿using System;
using System.Windows.Forms;
using MoneyWentWhere.WinFormsUI.UI.DataGrid;
using System.ComponentModel;
using System.Diagnostics;

namespace MoneyWentWhere.WinFormsUI.UI
{
    public sealed class DropDownEditingControl<T> : CustomComboBox.CustomComboBox, IDataGridViewEditingControl
        where T : Control 
    {
        DataGridView _dataGridView;
        private bool _valueChanged = false;
        private bool _valueIntialized = false;
        int _rowIndex;

        public DropDownEditingControl() 
            : base(Activator.CreateInstance<T>())
        {
            this.DropDownSizeMode = SizeMode.UseControlSize;

            IDropDownControl<T> ddc = DropDownControl as IDropDownControl<T>;
            if (ddc != null) { ddc.InitializeHost(this); }
        }

        // Implements the IDataGridViewEditingControl.EditingControlFormattedValue 
        // property.
        public object EditingControlFormattedValue
        {
            get
            {
                return this.Text;
            }
            set
            {
                Trace.WriteLine("EditingControlFormattedValue: " + value);

                // Called by the framework to set the value
                _valueIntialized = false;
                _valueChanged = false;

                if (value != null)
                {
                    TypeConverter converter = TypeDescriptor.GetConverter(value);
                    Text = converter.ConvertToString(value);
                }
                else
                {
                    Text = "";
                }
                _valueIntialized = true;
            }
        }

        // Implements the 
        // IDataGridViewEditingControl.GetEditingControlFormattedValue method.
        public object GetEditingControlFormattedValue(
            DataGridViewDataErrorContexts context)
        {
            return EditingControlFormattedValue;
        }

        // Implements the 
        // IDataGridViewEditingControl.ApplyCellStyleToEditingControl method.
        public void ApplyCellStyleToEditingControl(
            DataGridViewCellStyle dataGridViewCellStyle)
        {
            this.Font = dataGridViewCellStyle.Font;
        }

        // Implements the IDataGridViewEditingControl.EditingControlRowIndex 
        // property.
        public int EditingControlRowIndex
        {
            get
            {
                return _rowIndex;
            }
            set
            {
                _rowIndex = value;
            }
        }

        // Implements the IDataGridViewEditingControl.EditingControlWantsInputKey 
        // method.
        public bool EditingControlWantsInputKey(
            Keys key, bool dataGridViewWantsInputKey)
        {
            // TODO: will need to tweak depending on conditions

            // Up and down should probably pop up/down the combo box,
            // depending on the state. Keys should be in text etc.

            switch (key)
            {
                // Navigate grid
                case Keys.Escape:
                case Keys.Tab:
                case Keys.Enter:
                    return false;

                case Keys.Left:
                    return base.SelectionStart != 0 ||
                        base.SelectionLength != 0;
                case Keys.Right:
                    return base.SelectionStart != base.Text.Length ||
                        base.SelectionLength != 0;

                // Pop up/down
                case Keys.Down | Keys.Alt:
                case Keys.Up | Keys.Alt:
                    return true;

                default:
                    return false;
            }
            
        }

        // Implements the IDataGridViewEditingControl.PrepareEditingControlForEdit 
        // method.
        public void PrepareEditingControlForEdit(bool selectAll)
        {
            // No preparation needs to be done.
        }

        // Implements the IDataGridViewEditingControl
        // .RepositionEditingControlOnValueChange property.
        public bool RepositionEditingControlOnValueChange
        {
            get
            {
                return false;
            }
        }

        // Implements the IDataGridViewEditingControl
        // .EditingControlDataGridView property.
        public DataGridView EditingControlDataGridView
        {
            get
            {
                return _dataGridView;
            }
            set
            {
                _dataGridView = value;
            }
        }

        // Implements the IDataGridViewEditingControl
        // .EditingControlValueChanged property.
        public bool EditingControlValueChanged
        {
            get
            {
                return _valueChanged;
            }
            set
            {
                _valueChanged = value;
            }
        }

        // Implements the IDataGridViewEditingControl
        // .EditingPanelCursor property.
        public Cursor EditingPanelCursor
        {
            get
            {
                return base.Cursor;
            }
        }

        protected override void OnTextChanged(EventArgs e)
        {
            // Should not notify when value is set by the framework
            // on cell changes.
            if (!_valueIntialized) { return; }

            // Notify the DataGridView that the contents of the cell
            // have changed.
            _valueChanged = true;
            this.EditingControlDataGridView.NotifyCurrentCellDirty(true);
            base.OnTextChanged(e);
        }
    }
}
